import os
from typing import List


class FileTool:
    def __init__(self, workspace_dir: str = "/workspace"):
        self.workspace_dir = workspace_dir
        os.makedirs(workspace_dir, exist_ok=True)

    def list_files(self, directory: str = "") -> List[str]:
        """列出工作目录中的文件 - 支持子目录"""
        try:
            target_dir = os.path.join(self.workspace_dir, directory)
            if not os.path.exists(target_dir):
                return [f"❌ 目录不存在: {directory}"]

            files = []
            for root, dirs, filenames in os.walk(target_dir):
                # 计算相对路径
                rel_root = os.path.relpath(root, self.workspace_dir)
                if rel_root == ".":
                    rel_root = ""

                # 添加目录
                for dir_name in dirs:
                    dir_path = os.path.join(rel_root, dir_name) if rel_root else dir_name
                    files.append(f"📁 {dir_path}/")

                # 添加文件
                for filename in filenames:
                    file_path = os.path.join(rel_root, filename) if rel_root else filename
                    file_size = os.path.getsize(os.path.join(root, filename))
                    files.append(f"📄 {file_path} ({file_size} bytes)")

                break  # 只显示当前目录，不递归子目录

            return files if files else ["📁 目录为空"]

        except Exception as e:
            return [f"❌ 读取目录失败: {str(e)}"]

    def read_file(self, filepath: str) -> str:
        """读取文件内容 - 支持路径"""
        try:
            # 构建完整路径
            full_path = os.path.join(self.workspace_dir, filepath)

            # 安全检查：确保路径在 workspace 内
            if not os.path.abspath(full_path).startswith(os.path.abspath(self.workspace_dir)):
                return "❌ 错误：文件路径超出工作目录范围"

            if not os.path.exists(full_path):
                return f"❌ 文件不存在: {filepath}"

            if os.path.isdir(full_path):
                return f"❌ 路径是目录，不是文件: {filepath}"

            # 检查文件大小，避免读取过大文件
            file_size = os.path.getsize(full_path)
            if file_size > 10 * 1024 * 1024:  # 10MB限制
                return f"❌ 文件过大 ({file_size} bytes)，请选择小于10MB的文件"

            # 根据文件类型选择合适的编码
            try:
                with open(full_path, 'r', encoding='utf-8') as f:
                    content = f.read()
            except UnicodeDecodeError:
                try:
                    with open(full_path, 'r', encoding='gbk') as f:
                        content = f.read()
                except UnicodeDecodeError:
                    return f"❌ 无法解码文件内容（尝试了UTF-8和GBK编码）"

            return content

        except Exception as e:
            return f"❌ 读取文件失败: {str(e)}"

    def write_file(self, filepath: str, content: str) -> str:
        """写入文件 - 支持路径和自动创建目录"""
        try:
            # 构建完整路径
            full_path = os.path.join(self.workspace_dir, filepath)

            # 安全检查：确保路径在 workspace 内
            if not os.path.abspath(full_path).startswith(os.path.abspath(self.workspace_dir)):
                return "❌ 错误：文件路径超出工作目录范围"

            # 创建目录（如果不存在）
            directory = os.path.dirname(full_path)
            if directory and not os.path.exists(directory):
                os.makedirs(directory, exist_ok=True)

            # 写入文件
            with open(full_path, 'w', encoding='utf-8') as f:
                f.write(content)

            return f"✅ 文件保存成功: {filepath}"

        except Exception as e:
            return f"❌ 保存文件失败: {str(e)}"

    def get_file_info(self, filepath: str) -> str:
        """获取文件信息"""
        try:
            full_path = os.path.join(self.workspace_dir, filepath)

            if not os.path.exists(full_path):
                return f"❌ 文件不存在: {filepath}"

            if os.path.isdir(full_path):
                return f"📁 这是一个目录: {filepath}"

            stats = os.stat(full_path)
            return (
                f"📄 文件信息: {filepath}\n"
                f"📏 大小: {stats.st_size} bytes\n"
                f"📅 修改时间: {stats.st_mtime}\n"
                f"🔒 权限: {oct(stats.st_mode)[-3:]}"
            )

        except Exception as e:
            return f"❌ 获取文件信息失败: {str(e)}"